package com.xbongbong.saas.factory.publicrule;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.saas.domain.entity.CustomerRuleEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.RuleCustomerEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.enums.CustomerRuleChildEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 无签订合同客户规则功能类
 * @author : chy
 * @date 创建时间：2018-5-16 下午6:51:08
 * @version v3.22
 */
@Component
public class CheckRuleNoContract extends AbstractCheckRule implements ICheckRule {

	private static final Logger LOGGER = LoggerFactory.getLogger(CheckRuleNoContract.class);


	@Override
	public boolean canGainCustomer(CustomerRuleEntity rule, String corpid,
								   UserEntity userEntity, Long customerId, int dataIdSize, JSONObject data) throws XbbException {
		//此规则不会限制员工获取客户，故返回true;
		return true;
	}

	@Override
	public List<RuleCustomerEntity> getBackCustomerList(UserEntity userEntity,
														CustomerRuleEntity rule, List<RuleCustomerEntity> customerList,
														Integer advanceTime) throws XbbException {
		if(advanceTime == null){
			advanceTime = 0;
		}

		List<RuleCustomerEntity> retList = new ArrayList<>();
		if(rule == null || Objects.equals(rule.getStatus(), 0)){
			return retList;
		}
		String corpid = userEntity.getCorpid();
		IOperateRuleValue operateRuleValue = OperateRuleValueFactory.operateRuleValueFactory(rule.getRuleType());
		Object ruleValueObject = operateRuleValue.toObject(rule);
		JSONObject ruleValueJson = (JSONObject)ruleValueObject;

		Integer contract = ruleValueJson.getInteger("contract");
		Integer opportunity = ruleValueJson.getInteger("opportunity");
		List<String> typeNotIn = JSON.parseArray(ruleValueJson.getJSONArray("customerStatus").toJSONString(), String.class);
		removeRuleNoBack(corpid, customerList, contract, opportunity, typeNotIn);

		Integer type = ruleValueJson.getInteger("type");

		List<Long> labelNotIn = null;
		if (ruleValueJson.containsKey("label")) {
			labelNotIn = JSON.parseArray(ruleValueJson.getJSONArray("label").toJSONString(), Long.class);
		}
		removeRuleLabelNoBack(customerList, labelNotIn);

		if (Objects.equals(type, CustomerRuleChildEnum.LABEL.getCode())) {
			//获取当前用户的最小配置
			/**
			 * key:标签的id
			 * value：天数
			 */
			Map<Long, Integer> mainDayMap = getMinDayMap(ruleValueJson.getJSONArray("restrict"), userEntity);

			Integer day = null;

			Map<Long, CustomerUserEntity> customerUserMap = getCustomerUserMap(userEntity.getCorpid(), userEntity.getUserId(), customerList);

			for (RuleCustomerEntity customer : customerList) {
				String labelStr = customer.getLabels();
				List<Long> labels = JSONArray.parseArray(labelStr, Long.class);

				day = minDay(labels, mainDayMap);
				//没有在规则限制中
				if(day == null){
					continue ;
				}
				//原天数
				Integer orDay = day;
				day -= advanceTime;
				day = day < 0 ? 0 : day;
				Long second = day * 86400L;

				//day过大 Long溢出
				if(day > 0 && second < 0L){
					continue;
				}

				//客户被分配至今是否没有超过规则时间
				CustomerUserEntity customerUser = customerUserMap.get(customer.getId());
				if(!distributionTimeExceedRuleTime(customerUser, day)){
					continue ;
				}

				Long startTime = DateTimeUtil.getInt();
				//获取最近一条新签合同
				ContractEntityExt latestContract = getLatestEntityByCustomerId(corpid, customer.getId());
				String paramStr = "corpid:" + corpid + "customerId:" + customer.getId();
				//最新签订签合同在规则时间内
				boolean flag = false;
				Long signTime = null;
				if (Objects.nonNull(latestContract)) {
					signTime = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
					signTime = signTime == null ? 0L : signTime;
					flag = (DateTimeUtil.getInt() - signTime) < second;
				}
				if(!flag){
					if(advanceTime > 0) {
						//分配时间为默认的最新的签订时间 customerUserMap.get(customer.getId()) == null 时， 在方法distributionTimeExceedRuleTime后已结束
						Long latestSignTime = customerUserMap.get(customer.getId()).getDistributionTime();
						if(latestContract != null) {
							//签订时间大于分配时间，更新最新的签订时间
							latestSignTime = signTime > latestSignTime ? signTime : latestSignTime;
						}
						Long time = customerUser.getDistributionTime() > latestSignTime
								?customerUser.getDistributionTime():latestSignTime;
						setLeftDay(customer, userEntity.getName(), rule.getRuleType(), time, orDay);
					}
					retList.add(customer);
				}
			}
			return retList;
		}

		//获取当前用户的最小配置
		/**
		 * key:value
		 * {"1":2,"2":6,"3":5}
		 */
		JSONObject minObject = getMinObject(ruleValueJson.getJSONArray("restrict"), userEntity, type);


		Integer day = null;

		Map<Long, CustomerUserEntity> customerUserMap = getCustomerUserMap(corpid, userEntity.getUserId(), customerList);

		for(RuleCustomerEntity customer : customerList){
			if(Objects.equals(type, 0)){
				//所有客户统一配置
				day = (Integer) minObject.get("0");
			} else if (Objects.equals(type, 1)){
				//根据客户状态配置
//				Integer customerType = customer.getData().getInteger(CustomerManagementEnum.TYPE.getAttr());
				Integer customerType = customer.getType();
				day = (Integer) minObject.get(customerType + "");
			} else if (Objects.equals(type, 2)){
				//根据客户重要程度配置
//				Integer importantDegree = customer.getData().getInteger(CustomerManagementEnum.IMPORTANT_DEGREE.getAttr());
				Integer importantDegree = customer.getImportantDegree();
				//一星及以下的处理
				if(importantDegree == null || Objects.equals(importantDegree, 0)){
					importantDegree = 1;
				}

				day = (Integer) minObject.get(importantDegree + "");
			}
			//没有在规则限制中
			if(day == null){
				continue ;
			}
            //原天数
            Integer orDay = day;
			day -= advanceTime;
			day = day < 0 ? 0 : day;
			Long second = day * 86400L;

			//客户被分配至今是否没有超过规则时间
			CustomerUserEntity customerUser = customerUserMap.get(customer.getId());
			if(!distributionTimeExceedRuleTime(customerUser, day)){
				continue ;
			}
			Long startTime = DateTimeUtil.getInt();
			//获取最近一条新签合同
			ContractEntityExt latestContract = getLatestEntityByCustomerId(corpid, customer.getId());
			String paramStr = "corpid:" + corpid + "customerId:" + customer.getId();
			//最新签订签合同在规则时间内
			boolean flag = false;
			Long signTime = null;
			if (Objects.nonNull(latestContract)) {
				signTime = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
				signTime = signTime == null ? 0L : signTime;
				flag = (DateTimeUtil.getInt() - signTime) < second;
			}
			if(!flag){
				if(advanceTime > 0) {
					//分配时间为默认的最新的签订时间 customerUserMap.get(customer.getId()) == null 时， 在方法distributionTimeExceedRuleTime后已结束
					Long latestSignTime = customerUserMap.get(customer.getId()).getDistributionTime();
					if(latestContract != null) {
						//签订时间大于分配时间，更新最新的签订时间
						latestSignTime = signTime > latestSignTime ? signTime : latestSignTime;
					}
					Long time = customerUser.getDistributionTime() > latestSignTime
							?customerUser.getDistributionTime():latestSignTime;
					setLeftDay(customer, userEntity.getName(), rule.getRuleType(), time, orDay);
				}
				retList.add(customer);
			}
		}
		return retList;
	}

	private Integer minDay(List<Long> labels, Map<Long, Integer> minDayMap) {
		Integer day = null;
		if (CollectionsUtil.isEmpty(labels)) {
			return day;
		}
		for (Long label : labels) {
			Integer integer = minDayMap.get(label);
			if (Objects.nonNull(integer)) {
				if (Objects.isNull(day) || (Objects.nonNull(day) && integer < day)) {
					day = integer;
				}
			}
		}
		return day;
	}

	private Map<Long, Integer> getMinDayMap(JSONArray restrict, UserEntity userEntity) {
		Map<Long, Integer> specialMinDayMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
		Map<Long, Integer> allMinDayMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
		List<Long> deptIds;
		try {
			deptIds = JSONArray.parseArray(userEntity.getDepartment(), Long.class);
		} catch (Exception e) {
			deptIds = new ArrayList<>();
		}
		if (deptIds == null) {
			deptIds = new ArrayList<>();
		}
		List<Integer> roleIds = new ArrayList<>();
		String role = userEntity.getRoleIds();
		if (StringUtil.isNotEmpty(role)) {
			roleIds = StringUtil.roleIdToListInt(role);
		}
		if (roleIds == null) {
			roleIds = new ArrayList<>();
		}
		for(Object restrictObject : restrict){
			JSONObject restrictJson = (JSONObject)restrictObject;
			JSONArray users = restrictJson.getJSONArray("users");
			JSONArray depts = restrictJson.getJSONArray("depts");
			JSONArray roles = restrictJson.getJSONArray("roles");
			List<String> userIdList = new ArrayList<>();
			List<Long> deptIdList = new ArrayList<>();
			List<Integer> roleIdList = new ArrayList<>();
			if (Objects.nonNull(users)) {
				userIdList = JSON.parseArray(users.toJSONString(), String.class);
			}
			if (Objects.nonNull(depts)) {
				deptIdList = JSON.parseArray(depts.toJSONString(), Long.class);
			}
			if (Objects.nonNull(roles)) {
				roleIdList = JSON.parseArray(roles.toJSONString(), Integer.class);
			}
			deptIdList.retainAll(deptIds);
			roleIdList.retainAll(roleIds);
			Boolean scecialConfig = users != null || depts != null || roles != null;
			Boolean configFail = !userIdList.contains(userEntity.getUserId()) && deptIdList.isEmpty() && roleIdList.isEmpty();
			if(scecialConfig && configFail){
				//对于当前用户无效的配置
				continue ;
			}

			JSONArray array = restrictJson.getJSONArray("array");

			stringKey(array, users, depts, roles, specialMinDayMap, allMinDayMap);
		}
		Iterator<Map.Entry<Long, Integer>> it = allMinDayMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<Long, Integer> entry = it.next();
			Long key = entry.getKey();

			Integer integer = specialMinDayMap.get(key);
			if (Objects.nonNull(integer)) {
				// 如果某个标签出现在全部和特殊里面，那么去掉全部的标签配置；
				it.remove();
			}
		}
		specialMinDayMap.putAll(allMinDayMap);
		return specialMinDayMap;
	}

	private void stringKey(JSONArray array, JSONArray users, JSONArray depts, JSONArray roles, Map<Long, Integer> specialMinDayMap, Map<Long, Integer> allMinDayMap) {
		for(Object object : array){
			JSONObject jsonObject = (JSONObject)object;
			String key = jsonObject.getString("key");

			List<Long> labels = JSON.parseArray(key, Long.class);

			Integer value = jsonObject.getInteger("value");

			if(users == null && depts == null && roles == null){
				for (Long label : labels) {
					Integer integer = allMinDayMap.get(label);
					if (Objects.isNull(integer)) {
						allMinDayMap.put(label, value);
						continue;
					}
					if (integer < value) {
						allMinDayMap.put(label, integer);
					}
				}
				continue ;
			}

			for (Long label : labels) {
				Integer integer = specialMinDayMap.get(label);
				if (Objects.isNull(integer)) {
					specialMinDayMap.put(label, value);
					continue;
				}
				if (integer < value) {
					specialMinDayMap.put(label, integer);
				}
			}
		}
	}

	/**
	 * 获取最近一条新签合同
	 * @param corpid
	 * @param customerId
	 * @return
	 */
	public ContractEntityExt getLatestEntityByCustomerId(String corpid, Long customerId) throws XbbException {
		return contractModel.getLatestEntityByCustomerId(corpid, customerId);
	}


	@Override
	public List<RuleCustomerEntity> getBackCustomerList(UserEntity userEntity,
			CustomerRuleEntity rule, List<RuleCustomerEntity> customerList)
			throws XbbException {
		return getBackCustomerList(userEntity, rule, customerList, null);
	}

	@Override
	public JSONObject customerTypeChage(CustomerRuleEntity rule, List<ItemPoJo> typeItemPoJos) throws XbbException {
		return customerTypeChageBasic(rule, typeItemPoJos);
	}

}
